﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once
#include "GnufInputControl.h"
#include "GnufAppearanceSetting.h"
#include "GnufComponentDeclaration.h"

namespace gnuf {
    class Info;
    class Sprite;
    class ButtonControl;

    class GNUF_BASE_EXPORT IButtonControlHandler
        : public IInputControlHandler
    {
        DEFINE_CAST_DERIVED(gnuf::IButtonControlHandler, gnuf::IInputControlHandler)
    public:
        virtual void onClicked() = 0;
        virtual void onChecked(bool) {};
        virtual bool onSupportToSelect() const = 0;
    };

    class GNUF_BASE_EXPORT ButtonControlAdpatation
        : public InputControlAdaptation
    {
    protected:
        ButtonControlAdpatation();
        virtual ~ButtonControlAdpatation();

    public:
        ButtonControl * buttonControl() const;

        virtual void onClicked() {}
        virtual void onChecked(bool) {}
        virtual void onInfoChanged(const std::pair< const Info *, const Info * > &) {}
        virtual void assignCustomizeArrowInfo(const Info&) {}
        virtual void setCustomizeAppearanceSetting(gcmp::OwnerPtr<ButtonAppearanceSetting>&) {}
        virtual void setMaxCaptionCount(int val) {}
        virtual void showBadge(bool) {}
        virtual void setBadgeText(const std::wstring&) {}
        virtual void onToggled(bool) {}
        virtual void onGetLocation(std::set<const gcmp::UniqueString*>*) const {}
        virtual void onSpriteChanged(const Sprite &) {}
    };

    class GNUF_BASE_EXPORT ButtonControl final 
        : public InputControl
    {
        CANNOT_COPY_OR_ASSIGN(ButtonControl)
    public:
        static const EItemType Type;
        ButtonControl(IButtonControlHandler *, 
            gcmp::OwnerPtr< Info > & info, 
            gcmp::OwnerPtr< Info > & info2,
            bool wantToHandleToggling = false);
        virtual ~ButtonControl();

        IButtonControlHandler * buttonControlHandler() const;

        Info * info() { return m_twinsInfo.first.get(); }

        const Info * info() const   { return m_twinsInfo.first.get(); }
        const Info * info2() const  { return m_twinsInfo.second.get(); }
        void refreshExistedInfo(const std::list< Info > &);

        bool wantToHandleToggling() const { return m_wantToHandleToggling; }

        void setButtonInfo(const Info&, const ButtonControlAdpatation * trigger = nullptr);

        void setHotkey(const std::wstring & hotkey, const ButtonControlAdpatation * trigger = nullptr);

        void click(const ButtonControlAdpatation * trigger = nullptr);

        void setChecked(bool, const ButtonControlAdpatation * trigger = nullptr);
        bool isChecked() const { return m_checked; }

        void setCustomizeArrowIconInfo(const Info&, const ButtonControlAdpatation * trigger = nullptr);
        void setCustomizeAppearanceSetting(gcmp::OwnerPtr<ButtonAppearanceSetting>&, const ButtonControlAdpatation * trigger = nullptr);

        void setMaxCaptionCount(int val, const ButtonControlAdpatation * trigger = nullptr);

        void showBadge(bool, const ButtonControlAdpatation* trigger = nullptr);
        void setBadgeText(const std::wstring&, const ButtonControlAdpatation* trigger = nullptr);

        void setToggled(bool, const ButtonControlAdpatation* trigger = nullptr);
        bool isToggled() const { return m_toggled; }

        void setWantToBeTracked(bool val) { m_wantToBeTracked = val; }
        bool wantToBeTracked() const { return m_wantToBeTracked; }

        bool getLocations(std::set<const gcmp::UniqueString*>&) const;

        void setWantToShowAt(const EWorkStage workStage) { m_wantToShowAt = workStage; }
        bool wantToShowAt(const EWorkStage) const;

        void setSprite(const Sprite &, const ButtonControlAdpatation* trigger = nullptr);
        void clearSprite(const ButtonControlAdpatation* trigger = nullptr);

    private:
        std::pair<
            gcmp::OwnerPtr<Info>, // by default
            gcmp::OwnerPtr<Info>  // for toggling
        > m_twinsInfo;
        const bool m_wantToHandleToggling;
        bool m_checked;
        bool m_toggled;
        bool m_wantToBeTracked;
        EWorkStage m_wantToShowAt;
    };

}
